#include<iostream>//hdu 3031
#include<cstdio>
#include<algorithm>
using namespace std;

inline int rd(){int x;scanf("%d",&x);return x;}

const int maxv=  2200100;
int card[110][10100];
/**********************************/
int cnt;//左边堆的节点数，从1开始到cnt-1
struct node{//0表示空节点//大根堆变成小根堆，健值为负数就行了
	int k,dis;//k是健值，dis是距离
	int l,r,f,sz;//l是左，r是右，f是父亲,sz左偏堆的儿子和自己个数
	node(){}
	node(int a):k(a),dis(0),l(0),r(0),f(0),sz(1){}
}tr[maxv];
inline int troot(int a){//找堆顶元素的下标
	if(!a)return 0;
	while(tr[a].f)a=tr[a].f;
	return a;
}
inline int tmerge(int x,int y){//合并x与y堆
	int sz=tr[x].sz+tr[y].sz;
	if(!(x*y))return x+y; 
	if( tr[x].k<tr[y].k)	swap(x,y);
	int r=tmerge(tr[x].r,y),	l=tr[x].l;
	tr[x].r=r;tr[r].f=x;
	if(tr[r].dis>tr[l].dis)	swap(tr[x].l,tr[x].r);
	if(r) tr[x].dis=tr[r].dis+1;
	else tr[x].dis=0;
	tr[x].sz=sz;
	return x;
}
inline int tins(int i,int k,int& root){//在root下加一个元素i
	tr[i]=node(k);
	return root=tmerge(root,i);
}
inline node tpop(int& root){//取堆顶的，并且弹出堆顶元素
	node out=tr[root];
	int l=tr[root].l,r=tr[root].r;
	tr[root]=node(tr[root].k);
	tr[l].f=tr[r].f=0;
	root=tmerge(l,r);
	return out;
}
inline int tdel(int u){//删除u这个节点,返回现在的根
	if(!u)return u;
	int x,y,l,r;
	int &yl=tr[y].l,&yr=tr[y].r;//这里两个都要写引用吗？
	l=tr[u].l;r=tr[u].r;y=tr[u].f;
	tr[u]=node(tr[u].k);
	tr[x=tmerge(l,r)].f=y;
	if(y &&  yl==u) yl=x;
	if(y &&  yr==u) yr=x;
	for(;y;x=y,y=tr[y].f){
		if(tr[yr].dis>tr[yl].dis)swap(yl,yr);
		if(tr[yr].dis+1==tr[y].dis)break;
		tr[y].dis=tr[yr].dis+1;
	}
	if(x)return troot(x);
	else return troot(y);
}
inline int tadd(int i,int v){//tr[i].key+=v //返回根节点
	if(!i)return i;
	if(!(tr[i].l+tr[i].r+tr[i].f)){
		tr[i].k+=v;return i;
	}
	int kk=tr[i].k+v;
	int rt=tdel(i);
	return tins(i,kk,rt);
}
int n,m;
int to[1001],an[10];
int main()
{
    //freopen("in","r",stdin);
    int i,j,k,t;
    t=rd();
    int ans=0;
    while(t--)
    {
    	an[0]=-1; an[1]=-1;
    	/*****************/
    	cnt=1;//堆要从1开始
    	/*****************/
    	int x,y;
    	n=rd(); m=rd();
    	for(i=1; i<=m; i++)
    	{
    		x=rd(); 
    		card[i][0]=x;
    	}
    	for(i=1;i<=m; i++)
    	{
    		y=card[i][0];
			for(j=1;j<=card[i][0];j++)
			{
				x=rd();
				card[i][j]=x;
			}
			sort(&card[i][1],&card[i][y+1]);
	/**先把元素排序，然后建堆，注意1->n本来就是堆的顺序，所以直接合并就是****/
			if(y>=1)
			{
				x=cnt;
				to[i]=cnt;
				tr[cnt++]=node(card[i][1]);
				x=troot(x);
				for(j=2;j<=y;j++)
				{
					tr[cnt++]=node(card[i][j]);
					int tp=troot(cnt-1);//取出现在堆顶
				/*****************/
					x=tmerge(x,tp);//合并堆建堆,返回堆顶元素
				/*****************/
				}
	/******************************************/
			}
		}
		char ch[10];
		for(i=0; i<n; i++)
		{
			int now=i&1;
			scanf("%s",ch);
			if(ch[0]=='T')//合并堆
			{
				x=rd();
				int tp=troot(to[x]);
				if(an[now]==-1)
					an[now]=tp;
				else 
					an[now]=tmerge(an[now],tp);
			}
			else if(ch[0]=='C')//合并堆
			{
				int tpa=troot(an[now]);
				int tpb=troot(an[now^1]);
				if(tr[tpa].k>tr[tpb].k)
				{
					an[now]=tmerge(tpa,tpb);
					an[now^1]=-1;
				}
				else if(tr[tpa].k<tr[tpb].k)
				{
					an[now^1]=tmerge(tpb,tpa);
					an[now]=-1;
				}
			}
			else if(ch[0]=='L')//取出堆顶元素
			{
				int tpa=troot(an[now]);
				node ww=tpop(tpa);
			}
			else if(ch[0]=='A')//把堆顶元素加上某个值
			{
				x=rd();
				int tpa=troot(an[now]);
				an[now]=tadd(tpa,x);
			}
			else if(ch[0]=='E')//把堆顶元素加上某个值
			{
				x=rd();
				int tpa=troot(an[now]);
				x=x-tr[tpa].k;
				an[now]=tadd(tpa,x);
			}
		}
		int p,q;
		if(an[0]==-1)
    		p=0;
    	else
    	{
    		int tpa=troot(an[0]);
    		p=tr[tpa].sz;
    	}
    	if(an[1]==-1)
    		q=0;
    	else
    	{
    		int tpa=troot(an[1]);
    		q=tr[tpa].sz;
    	}
    	printf("%d:%d\n",p,q);
    	if(p>=q)
    		ans++;
    	else 	ans--;
    }
    if(ans>0)
    	puts("Hahaha...I win!!");
    else
    	puts("I will be back!!");
}
